/** 
 * File: Course.java
 * Project: CMSC 345 Course Registration System, Fall 2010
 * Author: David Chong
 * Date: 12/8/10
 * E-mail: ro62899@umbc.edu
 * This class is used to represent a User.  It contains fields to hold 
 * different stuff expected to be associated with a User such as a
 * name and campus ID.  The fields that are associated with all User are:
 * name, campusID, address, emailAddress, permissionLevel, and password.
 * Fields related to students include currentCoursesForStudent, 
 * waitListedCourses, completedCourses, gpa, isAlumni, major, minor, and 
 * isGradStudent.  Teachers have fields to hold the department that they belong
 * to.  In addition, the teacher has a teachingTheseCourses, 
 * previousCoursesTaught, and hasPermissionToExceedMaxCredits.  The 
 * permissionLevel is used to distinguish the type of User--student, teacher,
 * administrator.  The reason why one class was used instead multiple classes 
 * for different Users is that our customer, Neils Kasch, requested that the 
 * User may switch their type of role dynamically by administrators.  The class
 * contains methods to retrieve and modify fields.   In addition, there is 
 * methods to display the Course information.  The class implements the 
 * Comparable interface.
 *
 * 
 * Class Invariant: The integer fields can not be negative and the object
 *                  references can not be null.
 */


package registeringSystem;

import com.google.appengine.api.datastore.Key;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import java.util.ArrayList;

// could add gender
@PersistenceCapable
public class User implements Comparable<User> 
{
	@PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key theKey;
	
	// FIELDS RELATED TO ALL USERS
	@Persistent
	private String name;
	
	@Persistent
	private String campusID;
	
	@Persistent
	private String address;
	
	@Persistent
	private String emailAddress;
	
	@Persistent
	private int permissionLevel;
	
	@Persistent
	private String password;
	
	
	// FIELDS RELATED TO STUDENTS
	@Persistent
	private ArrayList<CoursePlusCharacter> currentCoursesForStudent;
	
	@Persistent
	private ArrayList<Course> waitListedCourses;
    
	@Persistent
	private ArrayList<CoursePlusCharacter> completedCourses;
	
	@Persistent
	private double gpa;
	
	@Persistent
	private boolean isAlumni;
	
	@Persistent
	private String major;
	
	@Persistent
	private String minor;
	
	@Persistent
	private boolean isGradStudent;
	
	
	// FIELDS RELATED TO TEACHERS
	@Persistent
	private String department;
	
	@Persistent
	private String linkToTeacherRating;
	
	@Persistent
	private ArrayList<Course> teachingTheseCourses;
	
	@Persistent
	private ArrayList<Course> previousCoursesTaught;
	
	@Persistent
	private boolean hasPermissionToExceedMaxCredits;
	
	
	
	/**
	 * Name: User <br><br>
	 * The default constructor used to initialize the private data members.
	 * <br><br>
	 * Precondition: None <br>
	 * Postcondition: The private data fields are initialized.
	 * @param None
	 */
	public User()
	{
		name = "";
		campusID = "";
		address = "";
		emailAddress = "";
		permissionLevel = 0;
		password = "";
		currentCoursesForStudent = new ArrayList<CoursePlusCharacter>();
		waitListedCourses = new ArrayList<Course>();
		completedCourses = new ArrayList<CoursePlusCharacter>();
		gpa = 0.0;
		isAlumni = false;
		major = "";
		minor = "";
		isGradStudent = false;
		department = "";
		linkToTeacherRating = "";
		teachingTheseCourses = new ArrayList<Course>();
		previousCoursesTaught = new ArrayList<Course>();
		hasPermissionToExceedMaxCredits = false;
	} // end of default constructor
	
	
	
	/**
	 * Name: User <br><br>
	 * The default constructor used to initialize the private data members.
	 * <br><br>
	 * Precondition: None <br>
	 * Postcondition: The private data fields are initialized.
	 * @param password - the password for the User object
	 */
	public User(String password) throws NullReferenceException
    {
        if(password == null)
            throw new NullReferenceException("Did not create the User " +
                                             "because a null reference was " +
                                             "passed in!\n");
		name = "";
		campusID = "";
		address = "";
		emailAddress = "";
		permissionLevel = 0;
		this.password = password;
		currentCoursesForStudent = new ArrayList<CoursePlusCharacter>();
		waitListedCourses = new ArrayList<Course>();
		completedCourses = new ArrayList<CoursePlusCharacter>();
		gpa = 0.0;
		isAlumni = false;
		major = "";
		minor = "";
		isGradStudent = false;
		department = "";
		linkToTeacherRating = "";
		teachingTheseCourses = new ArrayList<Course>();
		previousCoursesTaught = new ArrayList<Course>();
		hasPermissionToExceedMaxCredits = false;
	} // end of default constructor
	

	
	/**
	 * Name: User <br><br>
	 * Initializes the object's private data members with the values passed in.
	 * <br><br>
	 * Precondition: None <br>
	 * Postcondition: The private data fields are initialized.
	 * @param name - the name for the User
	 * @param address - the address
	 * @param emailAddress - the email address
	 * @param permissionLevel - the permission level for the User
	 * @param password - the password for the User
	 * @param major - the User's major
	 * @param minor - the User's minor
	 * @param isGradStudent - tells if the User is a graduate Student
	 * @param department - the User's department (teacher)
	 * @param linkToTeacherRating - a link to the teacher's rating
	 * @throws NotValidArgumentException is thrown if a negative number is 
	 *         passed in.
	 * @throws NullReferenceException is throwsn if a null reference is passed
	 *         in.
	 */
	public User(String name, String address, String emailAddress, 
			    int permissionLevel, String password, String major, 
			    String minor, boolean isGradStudent, String department, 
			    String linkToTeacherRating) 
	                                          throws NotValidArgumentException,
	                                                     NullReferenceException
	{
		if(name == null || address == null || emailAddress == null ||
		   password == null || major == null || minor == null ||
		   department == null || linkToTeacherRating == null)
			throw new NullReferenceException("Did not create the User " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		else if(permissionLevel < 0)
			throw new NotValidArgumentException("Did not create the User " +
					                            "because a negative number " +
					                            "was passed in!\n");
		
		this.name = name;
		campusID = "";
		this.address = address;
		this.emailAddress = emailAddress;
		this.permissionLevel = permissionLevel;
		this.password = password;
		currentCoursesForStudent = new ArrayList<CoursePlusCharacter>();
		waitListedCourses = new ArrayList<Course>();
		completedCourses = new ArrayList<CoursePlusCharacter>();
		gpa = 0;
		isAlumni = false;
		this.major = major;
		this.minor = minor;
		this.isGradStudent = isGradStudent;
		this.department = department;
		this.linkToTeacherRating = linkToTeacherRating;
		teachingTheseCourses = new ArrayList<Course>();
		previousCoursesTaught = new ArrayList<Course>();
		hasPermissionToExceedMaxCredits = false;
	} // end of constructor
	
	
	
	/**
	 * Name: User <br><br>
	 * Initializes the object's private data members with the values passed in.
	 * <br><br>
	 * Precondition: None <br>
	 * Postcondition: The private data fields are initialized.
	 * @param name - the name for the User
	 * @param campusID - the campus ID
	 * @param address - the address
	 * @param emailAddress - the email address
	 * @param permissionLevel - the permission level for the User
	 * @param password - the password for the User
	 * @param currentCoursesForStudent - the current Courses taken
	 * @param waitListedCourses - the wait listed Courses
	 * @param completedCourses - the completed Courses for the User
	 * @param gpa - the User's grade point average
	 * @param isAlumni - tells if the User is an alumni
	 * @param major - the User's major
	 * @param minor - the User's minor
	 * @param isGradStudent - tells if the User is a graduate Student
	 * @param department - the User's department (teacher)
	 * @param linkToTeacherRating - a link to the teacher's rating
	 * @param teachingTheseCourses - the Courses taught by the User
	 * @param previousCoursesTaught - the previous Courses taught by the User
	 * @param hasPermissionToExceedMaxCredits - tells if the User is allowed to
	 *                                          take more than the permitted
	 *                                          maximum number of credits
	 * @throws NotValidArgumentException is thrown if a negative number is 
	 *         passed in.
	 * @throws NullReferenceException is throwsn if a null reference is passed
	 *         in.
	 */
	public User(String name, String campusID, String address, 
			    String emailAddress, int permissionLevel, String password,
			    ArrayList<CoursePlusCharacter> currentCoursesForStudent,
			    ArrayList<Course> waitListedCourses,
			    ArrayList<CoursePlusCharacter> completedCourses, double gpa,
			    boolean isAlumni, String major, String minor, 
			    boolean isGradStudent, String department,  
			    String linkToTeacherRating, 
			    ArrayList<Course> teachingTheseCourses,
			    ArrayList<Course> previousCoursesTaught,
			    boolean hasPermissionToExceedMaxCredits) 
	                                          throws NotValidArgumentException,
	                                                     NullReferenceException
	{
		if(name == null || campusID == null || address == null ||
		   emailAddress == null || password == null ||
		   currentCoursesForStudent == null ||
		   waitListedCourses == null || completedCourses == null ||
		   major == null || minor == null || department == null ||
		   linkToTeacherRating == null || teachingTheseCourses == null ||
		   previousCoursesTaught == null)
			throw new NullReferenceException("Did not create the User " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		else if(permissionLevel < 0)
			throw new NotValidArgumentException("Did not create the User " +
					                            "because a negative value " +
					                            "was passed in!\n");
					                         
		this.name = name;
		this.campusID = campusID;
		this.address = address;
		this.emailAddress = emailAddress;
		this.permissionLevel = permissionLevel;
		this.password = password;
		this.currentCoursesForStudent = currentCoursesForStudent;
		this.waitListedCourses = waitListedCourses;
		this.completedCourses = completedCourses;
		this.gpa = gpa;
		this.isAlumni = isAlumni;
		this.major = major;
		this.minor = minor;
		this.isGradStudent = isGradStudent;
		this.department = department;
		this.linkToTeacherRating = linkToTeacherRating;
		this.teachingTheseCourses = teachingTheseCourses;
		this.previousCoursesTaught = previousCoursesTaught;
		this.hasPermissionToExceedMaxCredits = hasPermissionToExceedMaxCredits;
	} // end of constructor
	
	
	
	/** 
     * Name: User <br><br>
     * The copy constructor that initializes the private data members with the
     * same values with as the argument.  It is a deep copy.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Performs a deep copy of the argument object.
     * @param copyThis - the object that will be copied
     * @throws NullReferenceException is thrown is when a null reference is
     *         passed in
     */
    public User(User copyThis) throws NullReferenceException
    {
    	if(copyThis == null)
    		throw new NullReferenceException("Can not copy and create User " +
    				                         "object because a null reference " +
    				                         "was passed in!\n");
    	
    	name = copyThis.name;
    	campusID = copyThis.campusID;
    	address = copyThis.address;
    	emailAddress = copyThis.emailAddress;
    	permissionLevel = copyThis.permissionLevel;
    	password = copyThis.password;
    	copyCurrentCoursesForStudent(copyThis);
    	copyWaitListedCourses(copyThis);
    	copyCompletedCourses(copyThis);
    	gpa = copyThis.gpa;
    	isAlumni = copyThis.isAlumni;
    	major = copyThis.major;
    	minor = copyThis.minor;
    	isGradStudent = copyThis.isGradStudent;
    	department = copyThis.department;
    	linkToTeacherRating = copyThis.linkToTeacherRating;
    	copyTeachingTheseCourses(copyThis);
    	copyPreviousCoursesTaught(copyThis);
    	hasPermissionToExceedMaxCredits = copyThis.hasPermissionToExceedMaxCredits;
    } // end of copy constructor
    
	
	
    /** 
     * Name: copyCurrentCoursesForStudent <br><br>
     * Performs a deep copy for the argument object's current Courses
     * list for the student.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Performs a deep copy of the argument object's current
     *                Courses.
     * @param copyThis - the object that will be have its current Courses
     *                   copied
     */
    private void copyCurrentCoursesForStudent(User copyThis)
    {
		for(CoursePlusCharacter cpc: copyThis.currentCoursesForStudent)
		    try
		    {
		        currentCoursesForStudent.add(new CoursePlusCharacter(cpc));
		    }
		
		    catch(NullReferenceException nre)
		    {
		    	; // do nothing
		    }
	} // end of copyCurrentCoursesForStudent 
	
    
    
    /** 
     * Name: copyPreviousCoursesForStudent <br><br>
     * Performs a deep copy for the argument object's previous Courses
     * taught list.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Performs a deep copy of the argument object's previous
     *                Courses taught.
     * @param copyThis - the object that will have its previous Courses taught
     *                   copied 
     */
	private void copyPreviousCoursesTaught(User copyThis) 
	{
		for(Course theCourse: copyThis.previousCoursesTaught)
		    try
		    {
		        previousCoursesTaught.add(new Course(theCourse));
		    }
		
		    catch(NullReferenceException nre)
		    {
		    	; // do nothing
		    }
	} // end of copyPreviousCoursesTaught()

	
	
	/** 
     * Name: copyTeachingTheseCourses <br><br>
     * Performs a deep copy for the argument object's current Courses
     * taught by the User list.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Performs a deep copy of the argument object's current
     *                Courses taught.
     * @param copyThis - the object that will have its current Courses taught
     *                   copied 
     */
	private void copyTeachingTheseCourses(User copyThis) 
	{
		for(Course theCourse: copyThis.teachingTheseCourses)
		    try
		    {
		        teachingTheseCourses.add(new Course(theCourse));
		    }
		
		    catch(NullReferenceException nre)
		    {
		    	; // do nothing
		    }
	} // end of copyTeachingThesesCourses()

	
	
	/** 
     * Name: copyCompletedCourses <br><br>
     * Performs a deep copy for the argument object's completed Courses
     * list.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Performs a deep copy of the argument object's completed
     *                Courses.
     * @param copyThis - the object that will have its completed Courses taught
     *                   copied 
     */
	private void copyCompletedCourses(User copyThis) 
	{
		for(CoursePlusCharacter cpc: copyThis.completedCourses)
		    try
		    {
		        completedCourses.add(new CoursePlusCharacter(cpc));
		    }
		
		    catch(NullReferenceException nre)
		    {
		    	; // do nothing
		    }
	} // end of copyCompletedCourses()
	

	
	/** 
     * Name: copyWaitListedCourses <br><br>
     * Performs a deep copy for the argument object's wait listed Courses.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Performs a deep copy of the argument object's wait listed
     *                Courses taught.
     * @param copyThis - the object that will have its wait listed Courses
     *                   copied 
     */
	private void copyWaitListedCourses(User copyThis) 
	{
		for(Course theCourse: copyThis.waitListedCourses)
		    try
		    {
		        waitListedCourses.add(new Course(theCourse));
		    }
		
		    catch(NullReferenceException nre)
		    {
		    	; // do nothing
		    }
	} // end of copyWaitListedCourses()

	

	/** 
     * Name: getTheKey <br><br>
     * An accessor method that retrieves the key for the object in the
     * Google datastore.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the key. <br>
     * @param None
     */
	public Key getTheKey()
	{
		return theKey;
	} // end of getTheKey()
	
	
	
	/** 
     * Name: getName <br><br>
     * An accessor method that retrieves the name of the User.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the User's name. <br>
     * @param None
     */
	public String getName()
	{
		return name;
	} // end of getName()
	
	
	
	/** 
     * Name: getCampusID <br><br>
     * An accessor method that retrieves the campusID.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the campusID. <br>
     * @param None
     */
	public String getCampusID( )
	{
		return campusID;
	} // end of getCampusID()
	
	
	
	/** 
     * Name: getAddress <br><br>
     * An accessor method that retrieves the address.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the address. <br>
     * @param None
     */
	public String getAddress()
	{
		return address;
	} // end of getAddress()
	
	
	
	/** 
     * Name: getEmailAddress <br><br>
     * An accessor method that retrieves the e-mail address.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the e-mail address. <br>
     * @param None
     */
	public String getEmailAddress()
	{
		return emailAddress;
	} // end of getEmailAddress()
	
	
	
	/** 
     * Name: getPermissionLevel <br><br>
     * An accessor method that retrieves the permission level.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the permission level. <br>
     * @param None
     */
	public int getPermissionLevel()
	{
		return permissionLevel;
	} // end of getPermissionLevel()
	
	
	
	/** 
     * Name: getPassword <br><br>
     * An accessor method that retrieves the password.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the password. <br>
     * @param None
     */
	public String getPassword()
	{
		return password;
	} // end of getPassword()
	
	
	
	/** 
     * Name: getCurrentCoursesForStudent <br><br>
     * An accessor method that retrieves the current Courses for the Student.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the current courses for the Student. <br>
     * @param None
     */
	public ArrayList<CoursePlusCharacter> getCurrentCoursesForStudent()
	{
		return currentCoursesForStudent;
	} // end of getCurrentCoursesForStudent()
	
	
	
	/** 
     * Name: getCompletedCourses <br><br>
     * An accessor method that retrieves the completed Courses for the User.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the the completed courses for the User. <br>
     * @param None
     */
	public ArrayList<CoursePlusCharacter> getCompletedCourses()
	{
		return completedCourses;
	} // end of getCompletedCourses()
	
	
	
	/** 
     * Name: getGPA <br><br>
     * An accessor method that retrieves the User's gpa.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the User's gpa. <br>
     * @param None
     */
	public double getGPA()
	{
		return gpa;
	} // end of getGPA()
	
	
	
	/** 
     * Name: showNumberOfCreditsForThisSemester <br><br>
     * Calculates the number of credits that the User is currently taking.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a number representing the number of credits
     *                that the User is currently enrolled in. <br>
     * @param None
     */
	public int showNumberOfCreditsForThisSemester()
	{
		int numberOfCredits = 0;
		
		for(CoursePlusCharacter cpc: currentCoursesForStudent)
			numberOfCredits += cpc.getTheCourse().getNumberOfCredits();
		
		return numberOfCredits;
	} // end of getNumberOfCreditsForThisSemester()
	
	
	/** 
     * Name: getIsAlumni <br><br>
     * An accessor method that retrieves the if the User is an alumni.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the if the User is an alumni. <br>
     * @param None
     */
	public boolean getIsAlumni()
	{
		return isAlumni;
	} // end of getIsAlumni

	
	
	/** 
     * Name: getMajor <br><br>
     * An accessor method that retrieves the User's major.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the User's major. <br>
     * @param None
     */
	public String getMajor()
	{
		return major;
	} // end of getMajor()
	
	
	
	/** 
     * Name: getMinor <br><br>
     * An accessor method that retrieves the User's minor.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the User's minor. <br>
     * @param None
     */
	public String getMinor()
	{
		return minor;
	} // end of getMinor()
	
	
	
	/** 
     * Name: getIsGradStudent <br><br>
     * An accessor method that retrieves the if the User is a graduate student.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the if the User is a graduate student. <br>
     * @param None
     */
	public boolean getIsGradStudent()
	{
		return isGradStudent;
	} // end of getIsGradStudent()
	
	
	
	/** 
     * Name: getDepartment <br><br>
     * An accessor method that retrieves the department.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the department. <br>
     * @param None
     */
	public String getDepartment()
	{
		return department;
	} // end of getDepartment()
	
	
	
	/** 
     * Name: getLinkToTeacherRating <br><br>
     * An accessor method that retrieves the link to the teacher's rating.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the link to the teacher's rating. <br>
     * @param None
     */
	public String getLinkToTeacherRating()
	{
		return linkToTeacherRating;
	} // end of getLinkToTeacherRating()
	
	
	
	/** 
     * Name: getTeachingTheseCourses <br><br>
     * An accessor method that retrieves the courses that are taught by the
     * User.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the Courses that the User is teaching in the
     *                current semester. <br>
     * @param None
     */
	public ArrayList<Course> getTeachingTheseCourses()
	{
		return teachingTheseCourses;
	} // end of getTeachingTheseCourses()
	
	
	
	/** 
     * Name: getPreviousCoursesTaught <br><br>
     * An accessor method that retrieves the previousCoursesTaught.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the previousCoursesTaught time. <br>
     * @param None
     */
	public ArrayList<Course> getPreviousCoursesTaught()
	{
		return previousCoursesTaught;
	} // end of getPreviousCoursesTaught()
	
	
	
	/** 
	 * Name: getWaitListedCourses <br><br>
	 * An accessor method that retrieves the wait listed courses.
	 * <br><br>
	 * Precondition: None <br>
	 * Postcondition: Returns the wait listed courses. <br>
	 * @param None
	 */
	public ArrayList<Course> getWaitListedCourses()
	{
		return waitListedCourses;
	} // end of getWaitListedCourses()

	
	
	/** 
     * Name: getHasPermissionToExceedMaxCredits <br><br>
     * An accessor method that retrieves the if the User has permission to
     * exceed the maximum allowed number of credits in a semester.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the if the User is allow to exceed more than 20
     *                credits in a semester. <br>
     * @param None
     */
	public boolean getHasPermissionToExceedMaxCredits()
	{
		return hasPermissionToExceedMaxCredits;
	} // end of getHasPermissionToExceedMaxCredits()
	
    
	
	/** 
     * Name: setName <br><br>
     * A mutator to change the name field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the name to the value passed in.
     * <br>
     * @param name - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setName(String name) throws NullReferenceException
	{
		if(name == null)
			throw new NullReferenceException("Did not set the name " +
					                         "because a null reference was " +
					                         "passed in!\n");
		this.name = name;
	} // end of setName()
	
	
	
	/** 
     * Name: setCampusID <br><br>
     * A mutator to change the campusID field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the campusID to the value passed in.
     * <br>
     * @param campusID - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setCampusID(String campusID) throws NullReferenceException
	{
		if(campusID == null)
			throw new NullReferenceException("Did not set the campusID " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
	    this.campusID = campusID;	
	} // end of setCampusID()
	
	
	
	/** 
     * Name: setAddress <br><br>
     * A mutator to change the address field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the address to the value passed in.
     * <br>
     * @param address - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setAddress(String address) throws NullReferenceException
	{
		if(address == null)
			throw new NullReferenceException("Did not set the course name " +
					                         "because a null reference was " +
					                         "passed in!\n");
	    this.address = address;
	} // end of setAddress()
	
	
	
	/** 
     * Name: setEmailAddress <br><br>
     * A mutator to change the emailAddress field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the emailAddress to the value passed in.
     * <br>
     * @param emailAddress - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setEmailAddress(String emailAddress) 
	                                              throws NullReferenceException
	{
		if(emailAddress == null)
			throw new NullReferenceException("Did not set the email address " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		this.emailAddress = emailAddress;
	} // end of setEmailAddress()
	
	
	
	
	/** 
     * Name: setPermissionLevel <br><br>
     * A mutator to change the permissionLevel field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the permissionLevel to the value passed in.
     * <br>
     * @param permissionLevel - the argument that will be used to set the field
     * @throws NotValidArgumentException is thrown when a negative number is
     *         passed in.
     */
	public void setPermissionLevel(int permissionLevel) 
	                                            throws NotValidArgumentException
	{
		if(permissionLevel < 0)
			throw new NotValidArgumentException("Did not set the permission " +
					                            "level because a negative " +
					                            "number was passed in!\n");
		
		this.permissionLevel = permissionLevel;
	} // end of setPermissionLevel()
	
	
	
	
	/** 
     * Name: setPassword <br><br>
     * A mutator to change the password field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the password to the value passed in.
     * <br>
     * @param password - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setPassword(String password) throws NullReferenceException
	{
		if(password == null)
			throw new NullReferenceException("Did not set the password " +
					                         "because a null reference was " +
					                         "passed in!\n");
		this.password = password;
	} // end of setPassword()
	
	
	
	/** 
     * Name: setCurrentCoursesForStudent <br><br>
     * A mutator to change the currentCoursesForStudent field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the currentCoursesForStudent to the value passed
     *                in.
     * <br>
     * @param currentCoursesForStudent - the argument that will be used to set 
     *                                   the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setCurrentCoursesForStudent(ArrayList<CoursePlusCharacter> 
	                    currentCoursesForStudent) throws NullReferenceException
	{
		if(currentCoursesForStudent == null)
			throw new NullReferenceException("Did not set the current " +
					                         "courses for the student " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		this.currentCoursesForStudent = currentCoursesForStudent;
	} // end of setCurrentCoursesForStudent()
	
	
	
	/** 
     * Name: setCompletedCourses <br><br>
     * A mutator to change the completedCourses field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the completedCourses to the value passed in.
     * <br>
     * @param completedCourses - the argument that will be used to set the
     *                           field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setCompletedCourses(ArrayList<CoursePlusCharacter>
	                            completedCourses) throws NullReferenceException
	{
		if(completedCourses == null)
			throw new NullReferenceException("Did not set the completed " +
					                         "courses because a null " +
					                         "reference was passed in!\n");
		
	    this.completedCourses = completedCourses;	
	} // end of setCompletedCourses()
	


	/** 
     * Name: setGPA <br><br>
     * A mutator to change the gpa field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the gpa to the value passed in.
     * <br>
     * @param gpa - the argument that will be used to set the field
     * @throws NotValidArgumentException is thrown when a negative number is
     *         passed in.
     */
	public void setGPA(double gpa) throws NotValidArgumentException
	{
		if(gpa < 0)
			throw new NotValidArgumentException("Did not set the GPA " +
					                            "because a negative number " +
					                            "was passed in!\n");
		
		this.gpa = gpa;
	} // end of setGPA() 
	
	
	
	/** 
     * Name: setIsAlumni <br><br>
     * A mutator to change the isAlumni field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the isAlumni to the value passed in.
     * <br>
     * @param isAlumni - the argument that will be used to set the field
     */
	public void setIsAlumni(boolean isAlumni)
	{
		this.isAlumni = isAlumni;
	} // end of setIsAlumni()
	
	
	
	/** 
     * Name: setMajor <br><br>
     * A mutator to change the major field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the major to the value passed in.
     * <br>
     * @param major - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setMajor(String major) throws NullReferenceException
	{
		if(major == null)
			throw new NullReferenceException("Did not set the course name " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		this.major = major;
	} // end of setMajor()
	
	
	
	/** 
     * Name: setMinor <br><br>
     * A mutator to change the minor field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the minor to the value passed in.
     * <br>
     * @param minor - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setMinor(String minor) throws NullReferenceException
	{
		if(minor == null)
			throw new NullReferenceException("Did not set the minor because " +
					                         "a null reference was passed " +
					                         "in!\n");
		
		this.minor = minor;
	} // end of setMinor()
	
	
	
	/** 
     * Name: setIsGradStudent <br><br>
     * A mutator to change the isGradField field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the isGradField to the value passed in.
     * <br>
     * @param isGradField - the argument that will be used to set the field
     * @throws NotValidArgumentException is thrown when a null reference is
     *         passed in.
     */
	public void setIsGradStudent(boolean isGradStudent)
	{
		this.isGradStudent = isGradStudent;
	} // end of setIsGradStudent()
	
	
	
	/** 
     * Name: setDepartment <br><br>
     * A mutator to change the department field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the department to the value passed in.
     * <br>
     * @param department - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setDepartment(String department) throws NullReferenceException
	{
		if(department == null)
			throw new NullReferenceException("Did not set the department " +
					                         "because a null reference was " +
					                         "passed in!\n");
		this.department = department;
	} // end of setDepartment()
	
	
	
	/** 
     * Name: setLinkToTeacherRating <br><br>
     * A mutator to change the linkToTeacherRating field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the linkToTeacherRating to the value passed in.
     * <br>
     * @param linkToTeacherRating - the argument that will be used to set the
     *                              field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setLinkToTeacherRating(String linkToTeacherRating) 
	                                              throws NullReferenceException
	{
		if(linkToTeacherRating == null)
			throw new NullReferenceException("Did not set the link to the " +
					                         "teacher's rating because a " +
					                         "null reference was passed " +
					                         "in!\n");
		
		this.linkToTeacherRating = linkToTeacherRating;
	} // end of setLinkToTeacherRating()
	
	
	
	/** 
     * Name: setPreviousCoursesTaught <br><br>
     * A mutator to change the previousCoursesTaught field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the previousCoursesTaught to the value passed in.
     * <br>
     * @param prviousCoursesTaught - the argument that will be used to set the
     *        field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setPreviousCoursesTaught(
		 ArrayList<Course> previousCoursesTaught) throws NullReferenceException
	{
		if(previousCoursesTaught == null)
			throw new NullReferenceException("Did not set the previous " +
					                         "courses because a null " +
					                         "reference was passed in!\n");
		
		this.previousCoursesTaught = previousCoursesTaught;
	} // end of setPreviousCoursesTaught()
	
	
	
	/** 
     * Name: setCapacity <br><br>
     * A mutator to change the hasPermissionToExceedMaxCredits field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the hasPermissionToExceedMaxCredits to the value
     *                passed in.
     * <br>
     * @param hasPermissionToExceedMaxCredits - the argument that will be used
     *                                          to set the field
     */
	public void setHasPermissionToExceedMaxCredits(boolean 
			                                   hasPermissionToExceedMaxCredits)
	{
		this.hasPermissionToExceedMaxCredits = hasPermissionToExceedMaxCredits;
	} // end of setHasPermissionToExceedMaxCredits()
	
	
	
	/** 
     * Name: setWaitListedCourses <br><br>
     * A mutator to change the waitListedCourses field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the waitListedCourses to the value passed in.
     * <br>
     * @param waitListedCourses - the argument that will be used to set the 
     *        field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setWaitListedCourses(ArrayList<Course> waitListedCourses) 
	                                              throws NullReferenceException
	{
		if(waitListedCourses == null)
			throw new NullReferenceException("Did not set the wait listed " +
					                         "courses because a null " +
					                         "reference was passed in!\n");
		
		this.waitListedCourses = waitListedCourses;
	} // end of setWaitListedCourses()
	
	
	
	/** 
     * Name: showStudentInfo <br><br>
     * Displays the fields related to an student User.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a String displaying the User's information if 
     *                he/she is currently is an student. <br>
     * @param None
     */
	public String showStudentInfo()
	{
		return "Name: " + name + " (STUDENT)\n" +
	           "Campus ID: " + campusID + "\n" +
	           "E-Mail Address: " + emailAddress + "\n" +
	           "Major: " + major + "\n" +
	           "Minor: " + minor + "\n" +
	           //"Graduate Student" + isGradStudent  // MAYBE NOT NEED
	           "Grade Point Average: " + gpa + "\n" +
	           "Current Courses: " + "\n" + showStudentCourses();
	} // end of showStudentInfo()
	
	
	
	/** 
     * Name: showTeacherInfo <br><br>
     * Displays the fields related to an teacher User.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a String displaying the User's information if 
     *                he/she is currently is a teacher. <br>
     * @param None
     */
	public String showTeacherInfo()
	{
		return "Name: " + name + " (TEACHER)\n" +
		       "Campus ID: " + campusID + "\n" +
		       "Department: " + department + "\n" +
		       "E-Mail Address: " + emailAddress + "\n" +
		       "Teaching These Courses: " + "\n" + showCurrentCoursesTaught();
	} // end of showTeacherInfo()
	
	
	
	/** 
     * Name: showAdminInfo <br><br>
     * Displays the fields related to an administrator User.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a String displaying the User's information if 
     *                he/she is currently is an administrator. <br>
     * @param None
     */
	public String showAdminInfo()
	{
		return "Name: " + name + " (ADMIN)\n" +
	           "Campus ID: " + campusID + "\n" +
	           "E-Mail Address: " + emailAddress + "\n";
	} // end of showAdminInfo()
	
	
	
	/** 
     * Name: compareTo <br><br>
     * Compares two objects and returns a number stating the ordering between
     * two objects.  A positive number states that the calling object would
     * come after the other object.  In contrast a negative number would
     * represent a smaller number.  Zero means that the two object are
     * equivalent.  The objects calling this needs to check for 
     * NullPointerExceptions at runtime, so have this inside a try block.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a number stating the ordering relationship 
     *                between the calling object and the argument. <br>
     * @param theOtherUser - the other object will be compared
     * @throws NullPointerException is a unchecked exception that is thrown
     *         when a null argument is passed in
     */
	public int compareTo(User theOtherUser)
	{
		if(theOtherUser == null)
			throw new NullPointerException("Did not compare the object " +
					                       "because a null reference was " +
					                       "passed in!\n");
		
		return this.campusID.compareTo(theOtherUser.campusID);
	} // end of compareTo()
	
	
	
	/** 
     * Name: showStudentCourses <br><br>
     * Displays the current Courses taken by the User.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a String displaying the User's current Courses
     *                that he/she is taking. <br>
     * @param None
     */
	public String showStudentCourses()
	{
		String theCourses = "";
		
		for(CoursePlusCharacter theCourse: currentCoursesForStudent)
			theCourses += theCourse.getTheCourse().getCourseName() + "\n";
		
		return theCourses;
	} // end of showStudentCourses()
	
	
	
	/** 
     * Name: showCurrentCoursesTaught <br><br>
     * Displays the current Courses taught by the User.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a String displaying the User's current Courses
     *                that he/she is teaching. <br>
     * @param None
     */
	public String showCurrentCoursesTaught()
	{
		String returnedString = "";
		
		for(Course theCourse: teachingTheseCourses)
			returnedString += theCourse.getCourseName() + "\n";
		
		return returnedString;
	} // end of showCurrentCoursesTaught()
	
	
	
	/** 
     * Name: toString <br><br>
     * Displays the object's state.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a String representing the object's state.
     * <br>
     * @param None
     */
	public String toString()
	{
		return "Name:        " + name + "\n" +
		       "Campus ID:   " + campusID + "\n\n";
	} // end of toString()
	
	
	
	
	/** 
     * Name: arCurrentCoursesTaughtTheSame <br><br>
     * Compares the calling object and the passed in object's current
     * Courses are the same.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if the objects current are
     *                equal. <br>
     * @param otherUser - the User that will have its current Courses compared
     *                    to the calling object
     */
	private boolean areCurrentCoursesTheSame(User otherUser)
	{
		boolean theyAreEqual = true;
		
		for(int i = 0; i < currentCoursesForStudent.size() && 
		                                             theyAreEqual == true; i++)
			if(currentCoursesForStudent.get(i).equals(
					       otherUser.currentCoursesForStudent.get(i)) == false)
				theyAreEqual = false;
		
		return theyAreEqual;
	} // end of areTheCurrentCoursesTheSame()
	
	
	
	/** 
     * Name: arePreviousCoursesTaughtTheSame <br><br>
     * Compares the calling object and the passed in object's wait listed
     * Courses are the same.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if the objects wait listed are
     *                equal. <br>
     * @param otherUser - the User that will have its previous Courses compared
     *                    to the calling object
     */
	private boolean areWaitListedCoursesTheSame(User otherUser)
	{
		boolean theyAreEqual = true;
		
		for(int i = 0; i < waitListedCourses.size() && 
		                                             theyAreEqual == true; i++)
			if(waitListedCourses.get(i).equals(
					              otherUser.waitListedCourses.get(i)) == false)
				theyAreEqual = false;
		
		return theyAreEqual;
	} // end of areTheWaitListedCoursesTheSame()
	
	
	
	/** 
     * Name: areCompletedCoursesTheSame <br><br>
     * Compares the calling object and the passed in object's completed courses
     * are the same.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if the object's completed 
     *                Courses are equal. <br>
     * @param otherUser - the User that will have its completed Courses 
     *                    compared to the calling object
     */
	private boolean areCompletedCoursesTheSame(User otherUser)
	{
		boolean theyAreEqual = true;
		
		for(int i = 0; i < completedCourses.size() && 
		                                             theyAreEqual == true; i++)
			if(completedCourses.get(i).equals(
					               otherUser.completedCourses.get(i)) == false)
				theyAreEqual = false;
		
		return theyAreEqual;
	} // end of areTheCompletedCoursesTheSame()
	
	
	
	/** 
     * Name: areTeachingTheseCoursesTheSame <br><br>
     * Compares the calling object and the passed in object's teaching
     * Courses for the current semester are the same.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if the objects teaching
     *                current Courses are equal. <br>
     * @param otherUser - the User that will be compared to the calling object
     */
	private boolean areTeachingTheseCoursesTheSame(User otherUser)
	{
		boolean theyAreEqual = true;
		
		for(int i = 0; i < teachingTheseCourses.size() && 
		                                             theyAreEqual == true; i++)
			if(teachingTheseCourses.get(i).equals(
					           otherUser.teachingTheseCourses.get(i)) == false)
				theyAreEqual = false;
		
		return theyAreEqual;
	} // end of areTeachingTheseCoursesTheSame()
	
	
	
	/** 
     * Name: arePreviousCoursesTaughtTheSame <br><br>
     * Compares the calling object and the passed in object's previous
     * Courses are the same.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if the objects previous
     *                Courses are equal. <br>
     * @param otherUser - the User that will have its previous Courses
     *                    compared to the calling object
     */
	private boolean arePreviousCoursesTaughtTheSame(User otherUser)
	{
		boolean theyAreEqual = true;
		
		for(int i = 0; i < previousCoursesTaught.size() && 
		                                             theyAreEqual == true; i++)
			if(previousCoursesTaught.get(i).equals(
					       otherUser.previousCoursesTaught.get(i)) == false)
				theyAreEqual = false;
		
		return theyAreEqual;
	} // end of arePreviousCoursesTaughtTheSame()
	
	
	
	/** 
     * Name: equals <br><br>
     * Compares two objects and determines if they are equal.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if the object are equal. <br>
     * @param otherUser - the User that will be compared to the calling object
     */
	public boolean equals(User otherUser)
	{
		boolean areTheyEqual;
		
		if(otherUser == null)
			areTheyEqual = false;
	
		else
	        areTheyEqual = name.equals(otherUser.name) && 
	                       campusID.equals(otherUser.campusID) &&
	                       address.equals(otherUser.address) &&
	                       emailAddress.equals(otherUser.emailAddress) &&
	                       permissionLevel == otherUser.permissionLevel &&
	                       password.equals(otherUser.password) &&
	                       areCurrentCoursesTheSame(otherUser) &&
	                       areWaitListedCoursesTheSame(otherUser) &&
	                       areCompletedCoursesTheSame(otherUser) &&
	                       gpa == otherUser.gpa &&
	                       isAlumni == otherUser.isAlumni &&
	                       major.equals(otherUser.major) &&
	                       minor.equals(otherUser.minor) &&
	                       isGradStudent == otherUser.isGradStudent &&
	                       department.equals(otherUser.department) &&
	                       linkToTeacherRating.equals(
	                		                  otherUser.linkToTeacherRating) &&
	                       areTeachingTheseCoursesTheSame(otherUser) &&
	                       arePreviousCoursesTaughtTheSame(otherUser) &&
	                       hasPermissionToExceedMaxCredits ==
	                	             otherUser.hasPermissionToExceedMaxCredits;
		
		return areTheyEqual;
	} // end of equals()
} // end of User class